﻿
using System.Windows;
using MyFloridaHouse.libSvOpenDistricts.DataService;
using MyFloridaHouse.ServiceConn.DistrBldrSvcRef;
using System;
using System.Collections.Generic;
using MyFloridaHouse.libSvCommonUtilities;
using MyFloridaHouse.libSvUtilities;
using MyFloridaHouse.libSvUtilities.Logging;
using MyFloridaHouse.libSvOpenDistricts.MapShapes;

namespace MyFloridaHouse.libSvOpenDistricts.PDF
{


    // isolate the serviceDAL to isolate conversion of DTO definitions from DTO lib to Service Lib
    public class PDF_DAL
    {
        const string DistrictNotInView = "DISTRICT NOT IN VIEW";

        ServiceDAL serviceDAL;
        HouseMap pdfMap;

        public PDF_DAL(ServiceDAL serviceDAL)
        {
            this.serviceDAL = serviceDAL;
        }

        public void RegisterMap(HouseMap pdfMap)
        {
            this.pdfMap = pdfMap;
        }

        public void GetRegionShapesInView(int insetLayerListIndex, int layerID, double zoomLevel, MyFloridaHouse.libSvDTO.BoundingBoxDTO latLonInView)
        {
            if (null == pdfMap)
            {
                throw new Exception("Unable to get shapes for map, no map definted");
            }
            else
            {
                RegionShapesInViewSTO sto = new RegionShapesInViewSTO();
                sto.insetLayerListIndex = insetLayerListIndex;
                sto.layerID = layerID;
                sto.zoomLevel = zoomLevel;
                sto.north = latLonInView.northWest.latitude;
                sto.south = latLonInView.southEast.latitude;
                sto.east = latLonInView.southEast.longitude;
                sto.west = latLonInView.northWest.longitude;
                serviceDAL.ServiceDAL_GetRegionShapesInView(sto, GetRegionShapesInViewCompleted);
            }
        }


        private void GetRegionShapesInViewCompleted(object sender, GetRegionShapesInViewCompletedEventArgs args)
        {
            if (null != args.Error)
            {
                throw args.Error;
            }
            else if (null == args.Result)
            {
                throw new Exception("Unable to get shapes in view - no further information available");
            }
            else if ((string.Empty != args.Result.errorMessage) & (null != args.Result.errorMessage))
            {
                //TODO: change string to constant, it's defined in BoundingBoxRegions.cs - really bad I know, but my service references are convoluted right now
                if (!args.Result.errorMessage.Contains("No shapes found"))
                {
                    pdfMap.GetRegionShapesError(args.Result.errorMessage);
                }
                else
                {
                    pdfMap.GetRegionShapesNoShapes();
                }
            }
            else
            {
                UnpackRegionShapes(args.Result);

            }

            try
            {
                // must attempt from here to account for all possible ways that retrieve count can be modified
                pdfMap.AttemptDrawFinalMap();
            }
            catch (Exception ex)
            {
                Log.NotifyUser(ex.Message);
            }

        }

        private void UnpackRegionShapes(RegionShapesInViewSTO result)
        {
            try
            {
                MyFloridaHouse.libSvDTO.BoundingBoxDTO latLonInView = new MyFloridaHouse.libSvDTO.BoundingBoxDTO();
                latLonInView.northWest = new MyFloridaHouse.libSvDTO.PointDTO(result.north, result.west);
                latLonInView.southEast = new MyFloridaHouse.libSvDTO.PointDTO(result.south, result.east);

                List<RegionDTO> serverRegionList = new List<RegionDTO>();
                if (null == result.compressedRegionList)
                {
                    pdfMap.GetRegionShapesError("No regions returned for requestID " + result.insetLayerListIndex + " , layerID " + result.layerID);
                }
                else
                {

                    byte[] decompressed = CompressionManager.DecompressToByteArray((byte[])result.compressedRegionList);
                    serverRegionList = (List<RegionDTO>)SerializationManager.Deserialize(typeof(List<RegionDTO>), decompressed);


                    List<MyFloridaHouse.libSvDTO.RegionDTO> regionDTOList = MapShapeTools.ConvertServiceRegionDTOListtoLibSvDTO(serverRegionList);

                    pdfMap.SaveRegionShapes(result.insetLayerListIndex, result.layerID, regionDTOList);

                }
            }
            catch (Exception ex)
            {
                pdfMap.GetRegionShapesError(ex.Message);
            }
        }





        internal void GetDistrictShapeClipped(int clippedShapeID, int districtID, string iShapeUogIDList, MyFloridaHouse.libSvDTO.BoundingBoxDTO latLonInView)
        {
            if (null == pdfMap)
            {
                throw new Exception("Unable to get shapes for map, no map definted");
            }
            else
            {
                DistrictShapeClippedSTO sto = new DistrictShapeClippedSTO();
                sto.districtID = districtID;
                sto.clippedShapeID = clippedShapeID;
                sto.compressedShapeList = CompressionManager.Compress(iShapeUogIDList);
                sto.north = latLonInView.northWest.latitude;
                sto.south = latLonInView.southEast.latitude;
                sto.east = latLonInView.southEast.longitude;
                sto.west = latLonInView.northWest.longitude;
                serviceDAL.GetDistrictShapeClipped(sto, GetDistrictShapeClippedCompleted);
            }
        }

        private void GetDistrictShapeClippedCompleted(object sender, GetDistrictShapeClippedCompletedEventArgs args)
        {
            try
            {
                if (null != args.Error)
                {
                    pdfMap.GetClippedDistrictLabeIsError("Unable to get clipped districts - server error");
                }
                else if (null == args.Result)
                {
                    pdfMap.GetClippedDistrictLabeIsError("Unable to get clipped districts - no further information available");
                    throw new Exception("Unable to get clipped districts - no further information available");
                }
                else if ((string.Empty != args.Result.districtShapeSTO.errorMessage) & (null != args.Result.districtShapeSTO.errorMessage))
                {
                    // district not in view is not a fatal error, just means the district doesn't need to be displayed
                    if (args.Result.districtShapeSTO.errorMessage == DistrictNotInView)
                    {
                        pdfMap.GetClippedDistrictLabeIsNotInView();
                    }
                    else
                    {
                        pdfMap.GetClippedDistrictLabeIsError(args.Result.districtShapeSTO.errorMessage);
                    }

                }
                else
                {
                    // successfully got clipped district
                    libSvDTO.PointDTO centerPoint = new libSvDTO.PointDTO(args.Result.districtShapeSTO.centerPoint.latitude, args.Result.districtShapeSTO.centerPoint.longitude);
                    pdfMap.AttemptDrawClippedDistrictLabels(args.Result.clippedShapeID, args.Result.districtID, centerPoint);
                }
            }

            catch (Exception ex)
            {
                Log.NotifyUser(ex.Message);
            }



        }
    }
}
